﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace BusLineParser
{
    //http://www.fz-bus.cn/Index.asp 起始页面?
    //http://www.fz-bus.cn/Default.asp
    public partial class MainForm : Form
    {
        private static readonly Uri crackUri = new Uri("http://www.fz-bus.cn/Default.asp");
        //private static readonly Uri indexUri = new Uri("http://www.fz-bus.cn/Index.asp");
        private static readonly int TIMEOUT = 1000 * 100;
        private static readonly string initUri = @"http://www.fz-bus.cn/line_Search.asp?xianl=";
        private string sawContent = null;
        private CookieCollection sessionCookie = null;

        /// <summary>
        /// 候选要爬的线路
        /// </summary>
        private List<string> candidateList = new List<string>();
        /// <summary>
        /// 候选要爬的线路
        /// </summary>
        public List<string> CandidateList
        {
            get { return this.candidateList; }
        }
        /// <summary>
        /// 线路列表
        /// </summary>
        private List<LineInfo> lineList = new List<LineInfo>();

        /// <summary>
        /// 添加线路信息
        /// </summary>
        /// <param name="lineInfo"></param>
        private void AddLineInfo(LineInfo lineInfo)
        {
            this.lineList.Add(lineInfo);
        }

        private delegate void invokeDelegate();
        /// <summary>
        /// 显示抓取的总站点数
        /// </summary>
        private void SetCountLabel()
        {
            if (!this.labelCount.InvokeRequired)
                this.labelCount.Text = "抓取的站点有: " + this.lineList.Count + " 个";
            else
            {
                this.labelCount.Invoke(new invokeDelegate(this.SetCountLabel));
            }
        }

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (this.saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.tbPath.Text = this.saveFileDialog.FileName;
            }
        }

        /// <summary>
        /// 名字起得不好
        /// </summary>
        /// <param name="busline"></param>
        private delegate void SetCurrentLineDelegate(string busline);
        /// <summary>
        /// 显示当前正在解析的线路
        /// </summary>
        /// <param name="busLine"></param>
        private void SetCurrentLine(string busLine)
        {
            if (!this.lbCurrentLine.InvokeRequired)
                this.lbCurrentLine.Text = "当前正在解析的线路: " + busLine;
            else
            {
                this.lbCurrentLine.Invoke(new SetCurrentLineDelegate(this.SetCurrentLine), new object[] { busLine });
            }
        }
        private void ListResult(string lineInfo)
        {
            if (!this.tbSawContent.InvokeRequired)
                this.tbSawContent.Text += lineInfo;
            else
                this.tbSawContent.Invoke(new SetCurrentLineDelegate(this.ListResult), new object[] { lineInfo });
        }
        /// <summary>
        /// 后台采集线程
        /// </summary>
        private void Parser()
        {
            //2.采集;
            try
            {
                for (int i = 0; i < this.candidateList.Count; i++)
                {
                    this.SetCurrentLine(this.candidateList[i]);
                    string escapeQuery = System.Web.HttpUtility.UrlEncode(this.candidateList[i], Encoding.GetEncoding("gb2312"));
                    Uri siteUri = new Uri(MainForm.initUri + escapeQuery);
                    this.sawContent = this.GetContent(siteUri);

                    //3.解析;
                    LineInfo lineinfo = LineParser.GetLineInfo(this.sawContent, this.candidateList[i], this.CandidateList);
                    this.ListResult(lineinfo.ToString());
                    this.AddLineInfo(lineinfo);
                    this.SetCountLabel();
                }
                if (this.btnGo.InvokeRequired)
                    this.btnGo.Invoke(new EventHandler(this.SetButtonState));
                else
                    this.btnGo.Enabled = this.btnGo.Enabled ? false : true;
                this.DisplayMessage("本次线路抓取解析完成,总共抓取线路:" + this.lineList.Count + " 条!可以尝试更换起始线路以免遗漏!", false);
            }
            catch (Exception err)
            {
                this.DisplayMessage(err.Message, true);//这个既然不用封送处理?
                if (this.btnGo.InvokeRequired)
                    this.btnGo.Invoke(new EventHandler(this.SetButtonState));//2008年9月13日16:39:34,可以用通用的EventHandler处理,只是不能另外传参数
                else
                    this.btnGo.Enabled = this.btnGo.Enabled ? false : true;
            }
        }
        private void SetButtonState(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            if (btn != null)
                btn.Enabled = btn.Enabled ? false : true;
        }
        private void btnGo_Click(object sender, EventArgs e)
        {
            //1.准备;
            this.lineList.Clear();
            this.candidateList.Clear();
            LineParser.ClearLineDics();
            this.tbSawContent.Text = string.Empty;
            string startLine = this.GetStartLine();
            if (string.IsNullOrEmpty(startLine))
                return;
            this.candidateList.Add(startLine);

            this.btnGo.Enabled = false;
            //
            LineParser.SetFirstLine(startLine);
            Thread workThread = new Thread(new ThreadStart(this.Parser));
            workThread.IsBackground = true;
            workThread.Start();
           
        }
        /// <summary>
        /// 获取起始线路
        /// </summary>
        /// <returns></returns>
        private string GetStartLine()
        {
            string startLine = this.tbBusLine.Text.Trim();
            if (string.IsNullOrEmpty(startLine))
                this.DisplayMessage("起始线路不能为空", true);
            return startLine;
        }
        private void btnOutput_Click(object sender, EventArgs e)
        {
           
            //4.装载模板;
            //5.输出.
            if (string.IsNullOrEmpty(this.tbPath.Text))
            {
                DisplayMessage("输出路径不得为空", true);
                return;
            }
            try
            {
                using (StreamWriter sw = new StreamWriter(this.tbPath.Text, false, Encoding.Unicode))
                {
                    sw.WriteLine(";FZ公交数据 数据采集 by airwolf2026 玩手机的时候正好在学正则*_^^_*");
                    sw.WriteLine("[APPTITLE]=福州公交");
                    sw.WriteLine();
                    sw.WriteLine(";数据版本 以福州公交集团网站查询的到的数据为准,由程序自动采集.实际出行请以实际公交线路及交通情况为准,本数据仅供参考");
                    string dataVersion = "[DATAVERSION]=FZ" + DateTime.Now.ToString("yyyyMMdd");
                    sw.WriteLine(dataVersion);
                    sw.WriteLine();
                    sw.WriteLine(";以下公交数据起始站和终点站时刻以夏季时间为准,冬季一般相应扣减半小时");
                    sw.WriteLine(";本次采集的公交数据包含:" + this.lineList.Count + "条线路");
                    sw.WriteLine(";线路名称,起点站,起点站首班时间,起点站末班时间,终点站,终点站首班时间,终点站末班时间,类型,上行,下行,备注");
                    sw.WriteLine("[MAINDATASTART]");
                    //sort???
                    lineList.Sort();
                    foreach (LineInfo li in this.lineList)
                    {
                        sw.WriteLine(li.FormatbySymbian());
                    }
                    sw.WriteLine("[MAINDATAEND]");
                    sw.WriteLine();
                    DisplayMessage("数据输出完毕", false);
                }
            }
            catch (Exception err)
            {
                DisplayMessage(err.Message, true);
            }
        }
        /// <summary>
        /// 获取会话Cookie以便登录
        /// </summary>
        /// <returns>CookieCollection</returns>
        private void GetSessionCookie()
        {
            if (this.sessionCookie == null || this.sessionCookie.Count == 0)
            {
                HttpWebRequest req = null;
                try
                {
                    req = (HttpWebRequest)WebRequest.Create(MainForm.crackUri);
                    req.Timeout = MainForm.TIMEOUT;
                    req.KeepAlive = true;
                    req.CookieContainer = new CookieContainer();
                    HttpWebResponse response = (HttpWebResponse)req.GetResponse();

                    //this.DisplayMessage("cookies count is: " + response.Cookies.Count, false);
                    foreach (Cookie c in response.Cookies)
                    {
                        System.Diagnostics.Debug.WriteLine("cookieName: " + c.Name + " " + "cookieValue: " + c.Value);
                    }
                    if (response.Cookies.Count == 0)
                    {
                        throw new Exception("网站修改了规则,请重新分析源站点");
                    }
                    this.sessionCookie = response.Cookies;
                    response.Close();
                }
                catch (Exception e)
                {
                    this.DisplayMessage(e.Message, true);
                }
            }
        }
        /// <summary>
        /// 获取页面内容
        /// </summary>
        /// <param name="siteUri">站点URI</param>
        /// <returns>返回站点内容</returns>
        private string GetContent(Uri siteUri)
        {
            HttpWebRequest req = null;
            string content = null;
            try
            {
                this.GetSessionCookie();
                req = (HttpWebRequest)WebRequest.Create(siteUri);
                req.Timeout = MainForm.TIMEOUT;
                req.CookieContainer = new CookieContainer();
                req.CookieContainer.Add(this.sessionCookie);
                HttpWebResponse response = (HttpWebResponse)req.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.GetEncoding("gB2312"));

                content = reader.ReadToEnd();
                reader.Close();
                response.Close();
            }
            catch (Exception e)
            {
                this.DisplayMessage(e.Message, true);
            }
            return content;
        }
        /// <summary>
        /// 获取uri
        /// </summary>
        /// <returns></returns>
        private Uri GetUri()
        {
            string strUri = this.tbBusLine.Text.Trim();
            Uri siteUri = null;
            if (string.IsNullOrEmpty(strUri))
            {
                this.DisplayMessage("URL不得为空", true);
            }
            else
            {
                try
                {
                    siteUri = new Uri(strUri);
                }
                catch (ArgumentNullException e)
                {
                    this.DisplayMessage(e.Message, true);
                }
                catch (UriFormatException e)
                {
                    this.DisplayMessage(e.Message, true);

                }
            }
            return siteUri;

        }
        /// <summary>
        /// 显示出错信息或者提示信息
        /// </summary>
        /// <param name="message">要显示的消息</param>
        /// <param name="isWarning">是否是警告或者普通提示</param>
        private void DisplayMessage(string message,bool isWarning)
        {
            MessageBox.Show(message, "公交线路解析", MessageBoxButtons.OK, isWarning ? MessageBoxIcon.Warning : MessageBoxIcon.Information);
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(0);
        }

       
    }
}
